/*  

Cafechess Library: Cover basic chess programming needs, like GUI, Engine integration, 
FEN and PGN parsing.

                 \\|//
                 (o o)
--------------ooO-(_)-Ooo----------------------------------
Copyright (C) 2009  By Gregory A. Prentice Snoqualmie, WA
                    www.cafechess.org
                    cafechess@comcast.net
                      Oooo
--------------oooO----(  )---------------------------------
              (  )    (_/
               \_)

Microsoft Public License (Ms-PL)
               
Revisions:

Author        Date    Description:

*/
using System;
using System.Xml;
using System.Collections;
using Cafechess.Chess.Parsers;
namespace Cafechess.Control.Chessboard.Demo
{

  /// <summary>
  /// Summary description for PGNtoXML.
  /// </summary>
  public class PGNtoXML : IGameParserEvents
  {
    public XmlDocument GameDOM;    
    string coFilename;
    XmlNode coCurrent;
    XmlElement coMove;
    int count = 0;
    
    private Stack coSaveState;

    public PGNtoXML()
    {
      GameDOM = new XmlDocument();
      coSaveState = new Stack();
      count = 0;
      coMove = null;
    }
    public void open(string Filename)
    {
      coFilename = Filename;
      GameDOM.LoadXml("<GAMES>" +
        "</GAMES>");
      coCurrent = GameDOM.DocumentElement;
    }

    public void close()
    {
      GameDOM.Save(coFilename);      
    }

    public void NewGame(IGameParser iParser)
    {
      count++;
      coCurrent = GameDOM.DocumentElement;
      XmlElement newElement = GameDOM.CreateElement("GAME");
      coCurrent = coCurrent.AppendChild(newElement);
    }

    public void ExitHeader(IGameParser iParser)
    {
    }

    public void EnterVariation(IGameParser iParser)
    {
      coSaveState.Push( coLastNumber );
      if( coMove != null )
      {
        coCurrent.AppendChild(coMove);
        coMove = null;
      }
      XmlElement newElement = GameDOM.CreateElement("VARIATION");
      coCurrent = coCurrent.AppendChild(newElement);
    }

    public void ExitVariation(IGameParser iParser)
    {
      if( iParser.State != GameParserState.State.NUMBER )
        MoveParsed(iParser);
      if(coMove!=null)
      {
        coCurrent.AppendChild(coMove);
        coMove = null;
      }
      coCurrent = coCurrent.ParentNode;
      coLastNumber = (string)coSaveState.Pop();
    }
    public void Starting(IGameParser iParser)
    {

    }
    public void Finished(IGameParser iParser)
    {
      if(coMove != null )
      {
        coCurrent.AppendChild(coMove);
        coMove = null;
      }
      coCurrent = GameDOM.DocumentElement;
      coSaveState.Clear();
    }

    public void TagParsed(IGameParser iParser)
    {
      try
      {
        XmlElement newElement = GameDOM.CreateElement("TAG");
        newElement.SetAttribute("name",iParser.Tag);
        newElement.AppendChild(GameDOM.CreateTextNode(iParser.Value));
        coCurrent.AppendChild(newElement);   
      }
      catch(Exception err)
      {
        err.Message.ToUpper();
      }
    }
    public void CommentParsed(IGameParser iParser)
    {
      if( coMove != null )
      {
        coCurrent.AppendChild(coMove);
        coMove = null;
      }
      XmlElement newElement = GameDOM.CreateElement("COMMENT");
      newElement.AppendChild(GameDOM.CreateTextNode(iParser.Value));
      coCurrent.AppendChild(newElement);
    }
    public void NagParsed(IGameParser iParser)
    {
      if( coMove != null )
      {
        coCurrent.AppendChild(coMove);
        coMove = null;
      }
      XmlElement newElement = GameDOM.CreateElement("NAG");
      newElement.AppendChild(GameDOM.CreateTextNode(iParser.Value));
      coCurrent.AppendChild(newElement);
    }

    public void EndMarker(IGameParser iParser)
    {
      if( coMove != null )
      {
        coCurrent.AppendChild(coMove);
        coMove = null;
      }
      XmlElement newElement = GameDOM.CreateElement("END");
      newElement.AppendChild(GameDOM.CreateTextNode(iParser.Value));
      coCurrent.AppendChild(newElement);
    }


    string coLastNumber;
    public void MoveParsed(IGameParser iParser)
    {
      try
      {
        if( iParser.State == GameParserState.State.NUMBER )
        {
          // Checks for cases where someone has entered a move as: 1. e4 1...e5
          //  as we only save out our element when we have complete move list or
          //  we are entering a variation.
          if( coMove == null )
          {           
            coMove = GameDOM.CreateElement("MOVE");
            coLastNumber = iParser.Value;
            coMove.SetAttribute("number",coLastNumber);
          }
        }
        else if( iParser.State == GameParserState.State.WHITE )
        {
          if( coMove != null )
            coMove.SetAttribute("white",iParser.Value);
        }
        else if( iParser.State == GameParserState.State.BLACK )
        {
          if( coMove == null )
          {
            coMove = GameDOM.CreateElement("MOVE");
            coMove.SetAttribute("number",coLastNumber);
          }
          coMove.SetAttribute("black",iParser.Value);
          coCurrent.AppendChild(coMove);
          coMove = null;
        }
      }
      catch
      {

      }
    }
  }
}
